import { createModel } from 'hox';
import { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';

import { getMenus } from '@/services/system/menu';
import { ILoginParams, setLogin } from '@/services/user';
import { flatToNest, parseParam } from '@/utils';
import { getToken, removeToken, setToken } from '@/utils/cookies';

export interface IUser {
  token: string;
  id: string;
  avatarUrl?: string;
  nickname: string;
}

export interface IMenu {
  id: number;
  parent_id: string;
  title?: string;
  code: string;
  comment?: string;
  path: string;
  redirect?: string;
  order?: number;
  icon?: string;
  show: boolean;
}

const UserModel = () => {
  const history = useHistory();

  const [submitting, setSubmitting] = useState(false);
  const [loginMessage, setLoginMessage] = useState('');
  const [hasAuth, setHasAuth] = useState(false);
  const [user, setUser] = useState({});
  const [menus, setMenus] = useState([]);
  const [asideMenus, setAsideMenus] = useState([]);
  const [routes, setRoutes] = useState([]);

  const loginPath = '/login';

  useEffect(() => {
    const hasToken = getToken();
    const { pathname } = window.location;

    if (pathname !== loginPath) {
      if (hasToken) {
        menus.length === 0 && requestMenus();
      } else {
        window.location.href = loginPath;
      }
    }
  }, [hasAuth]);

  async function requestMenus() {
    const { data = [] } = await getMenus();
    if (data.length) {
      setRoutes(data);
      const asides = flatToNest(
        data
          .filter((v: IMenu) => v.show)
          .map((v: IMenu) => ({
            path: v.path,
            redirect: v.redirect,
            name: v.title,
            icon: v.icon,
            code: v.code,
            id: v.id,
            parent_id: v.parent_id,
          })),
      );
      setAsideMenus(asides);
      setMenus(flatToNest(data));
      setHasAuth(true);
    }
  }

  async function login(loginParams: ILoginParams) {
    setSubmitting(true);
    try {
      const { code, data } = await setLogin(loginParams);
      if (code === 2000) {
        setToken(data.token);
        setUser(data);
        setLoginMessage('');
        await requestMenus();

        const { redirect } = parseParam(window.location.href);
        history.replace(redirect || '/');
      } else {
        setLoginMessage('账户或密码错误');
      }
    } catch (e) {
      setLoginMessage('');
    } finally {
      setSubmitting(false);
    }
  }

  async function logout() {
    const redirect = window.location.href;
    if (window.location.pathname !== loginPath && !redirect) {
      removeToken();
      history.replace({
        pathname: loginPath,
        search: JSON.stringify({
          redirect: encodeURIComponent(redirect),
        }),
      });
    }
  }

  return {
    submitting,
    loginMessage,
    hasAuth,
    user,
    menus,
    routes,
    asideMenus,
    login,
    logout,
  };
};

export default createModel(UserModel);
